use std::io::{Read, Write};

fn main() -> std::io::Result<()>{
    println!("Hello, world!");
    println!("{:?}", cheapo_request("www.baidu.com", 80, "/"));
    // let response = async_std::task::block_on(request_get("www.baidu.com", 80, "/"));
    // println!("{:?}", response );

    let requests = vec![
        ("www.baidu.com".to_string(), 80, "/".to_string()),
        ("www.google.com".to_string(), 80, "/".to_string()),
        ("www.bing.com".to_string(), 80, "/".to_string()),
    ];

    let responses = async_std::task::block_on(many_requests(requests));
    for response in responses {
        match response {
            Ok(response) => println!("请求结果：{:?}", response),
            Err(e) => eprintln!("请求失败 ：{:?}", e),
        }
    }

    
    let requests = vec![
        // ("www.baidu.com".to_string(), 80, "/".to_string()),
        ("www.google.com".to_string(), 80, "/".to_string()),
        ("www.bing.com".to_string(), 80, "/".to_string()),
    ];

    let responses = async_std::task::block_on(many_requests2(requests));
    for response in responses {
        match response {
            Ok(response) => println!("请求结果：{:?}", response),
            Err(e) => eprintln!("请求失败 ：{:?}", e),
        }
    }

    let requests = vec![
        // ("www.baidu.com".to_string(), 80, "/".to_string()),
        ("www.google.com".to_string(), 80, "/".to_string()),
        ("www.bing.com".to_string(), 80, "/".to_string()),
    ];

    let responses = async_std::task::block_on(many_requests3(requests));
    for response in responses {
        match response {
            Ok(response) => println!("3请求结果：{:?}", response),
            Err(e) => eprintln!("3请求失败 ：{:?}", e),
        }
    }

    let requests = &["https://www.google.com".to_string(), "https://www.bing.com".to_string()];
    let responses = async_std::task::block_on(many_requests4(requests));
    for response in responses {
        match response {
            Ok(response) => println!("4请求结果：{:?}", response),
            Err(e) => eprintln!("4请求失败 ：{:?}", e),
        }
    }

    Ok(())
}


fn cheapo_request(host:&str, port:u16, path:&str) -> std::io::Result<String> {
    let mut socket = std::net::TcpStream::connect((host, port))?;
    let request = format!("GET {} HTTP/1.1\r\nHost:{}\r\n\r\n", path, host);
    socket.write_all(request.as_bytes())?;
    socket.shutdown(std::net::Shutdown::Write)?;

    let mut response = String::new();
    socket.read_to_string(&mut  response)?;

    Ok(response)
}

async fn request_get(host:&str, port:u16, path:&str) -> std::io::Result<String> {
    use async_std::io::prelude::*;

    let mut socket = async_std::net::TcpStream::connect((host, port)).await?;
    let request = format!("GET {} HTTP/1.1\r\nHost:{}\r\n\r\n", path, host);
    socket.write_all(request.as_bytes()).await?;
    socket.shutdown(async_std::net::Shutdown::Write)?;

    let mut response = String::new();
    socket.read_to_string(&mut  response).await?;

    Ok(response)
}

async fn owner_request_get(host:String, port:u16, path:String) -> std::io::Result<String> {
    request_get(&host, port, &path).await
}

async fn many_requests(requests: Vec<(String, u16,String)>) -> Vec<std::io::Result<String>> {
    use async_std::task;

    let mut handles = vec![];
    for(host, port, path) in requests {
        handles.push(task::spawn_local(owner_request_get(host, port, path)));
    }

    let mut requests = vec![];
    for handle in handles {
        requests.push(handle.await);
    }

    requests
}

async fn many_requests2(requests: Vec<(String, u16,String)>) -> Vec<std::io::Result<String>> {
    use async_std::task;

    let mut handles = vec![];
    for(host, port, path) in requests {
        // 使用 async 异步块，如闭包函数一样
        handles.push(task::spawn_local(async move {request_get(&host, port, &path).await}));
    }

    let mut requests = vec![];
    for handle in handles {
        requests.push(handle.await);
    }

    requests
}

async fn many_requests3(requests: Vec<(String, u16,String)>) -> Vec<std::io::Result<String>> {
    use async_std::task;

    let mut handles = vec![];
    for(host, port, path) in requests {
        // 使用 async 异步块，如闭包函数一样
        handles.push(task::spawn(async move {request_get(&host, port, &path).await}));
    }

    let mut requests = vec![];
    for handle in handles {
        requests.push(handle.await);
    }

    requests
}

async fn many_requests4(urls:&[String]) -> Vec<Result<String, surf::Error>> {
    use async_std::task;

    let client = surf::Client::new();


    let mut handles = vec![];
    for url in urls {
        // 使用 async 异步块，如闭包函数一样
        let request = client.get(&url).recv_string();
        handles.push(task::spawn(request));
    }

    let mut requests = vec![];
    for handle in handles {
        requests.push(handle.await);
    }

    requests
}